﻿using System;
using System.Collections.Generic;
using NetTopologySuite.Triangulate.QuadEdge;

namespace NetTopologySuite.Triangulate
{
	public class IncrementalDelaunayTriangulator
	{
		public IncrementalDelaunayTriangulator(QuadEdgeSubdivision subdiv)
		{
			this._subdiv = subdiv;
			this._isUsingTolerance = (subdiv.Tolerance > 0.0);
		}

		public void InsertSites(ICollection<Vertex> vertices)
		{
			foreach (Vertex v in vertices)
			{
				this.InsertSite(v);
			}
		}

        public NetTopologySuite.Triangulate.QuadEdge.QuadEdge InsertSite(Vertex v)
		{
            NetTopologySuite.Triangulate.QuadEdge.QuadEdge quadEdge = this._subdiv.Locate(v);
			if (this._subdiv.IsVertexOfEdge(quadEdge, v))
			{
				return quadEdge;
			}
			if (this._subdiv.IsOnEdge(quadEdge, v.Coordinate))
			{
				quadEdge = quadEdge.OPrev;
				this._subdiv.Delete(quadEdge.ONext);
			}
            NetTopologySuite.Triangulate.QuadEdge.QuadEdge quadEdge2 = this._subdiv.MakeEdge(quadEdge.Orig, v);
            NetTopologySuite.Triangulate.QuadEdge.QuadEdge.Splice(quadEdge2, quadEdge);
            NetTopologySuite.Triangulate.QuadEdge.QuadEdge quadEdge3 = quadEdge2;
			do
			{
				quadEdge2 = this._subdiv.Connect(quadEdge, quadEdge2.Sym);
				quadEdge = quadEdge2.OPrev;
			}
			while (quadEdge.LNext != quadEdge3);
			for (;;)
			{
                NetTopologySuite.Triangulate.QuadEdge.QuadEdge oprev = quadEdge.OPrev;
				if (oprev.Dest.RightOf(quadEdge) && v.IsInCircle(quadEdge.Orig, oprev.Dest, quadEdge.Dest))
				{
                    NetTopologySuite.Triangulate.QuadEdge.QuadEdge.Swap(quadEdge);
					quadEdge = quadEdge.OPrev;
				}
				else
				{
					if (quadEdge.ONext == quadEdge3)
					{
						break;
					}
					quadEdge = quadEdge.ONext.LPrev;
				}
			}
			return quadEdge2;
		}

		private readonly QuadEdgeSubdivision _subdiv;

		private bool _isUsingTolerance;
	}
}
